// 非虚接口模式（NVI）详解与示例
// 非虚接口模式（Non-Virtual Interface，NVI）是一种设计模式，它通过公共的非虚函数来封装虚函数的调用。
// 下面我将详细解释NVI模式并提供多个实际使用场景的例子。

// NVI模式的基本结构
class Base
{
public:
    // 公共非虚函数（接口）
    void service()
    {
        // 前置条件检查
        beforeService();

        // 调用虚函数（可被子类重写的实现）
        doService();

        // 后置条件检查
        afterService();
    }

protected:
    // 私有或保护的虚函数（实现）
    virtual void doService()
    {
        // 默认实现
    }

    // 可选的钩子函数
    virtual void beforeService() { /* 默认为空 */ }
    virtual void afterService() { /* 默认为空 */ }
};

class Derived : public Base
{
protected:
    // 重写虚函数
    virtual void doService() override
    {
        // 派生类特定实现
    }
};
// NVI模式的优势
// 1.强制执行不变量：可以在调用虚函数前后执行必要的检查和操作
// 2.集中管理默认参数：避免条款37中提到的默认参数问题
// 3.提高封装性：实现细节（虚函数）对客户端代码不可见
// 4.遵循"模板方法"设计模式：定义算法的骨架，允许子类重定义特定步骤

// 实际使用场景示例
// 示例1：数据库连接
class DBConnection
{
public:
    // 非虚接口
    bool connect(const std::string &connectionString = "default_connection")
    {
        std::cout << "Preparing to connect..." << std::endl;

        // 记录连接尝试
        logConnectionAttempt(connectionString);

        // 调用可被重写的实现
        bool success = doConnect(connectionString);

        // 记录连接结果
        if (success)
        {
            std::cout << "Connection successful" << std::endl;
        }
        else
        {
            std::cout << "Connection failed" << std::endl;
        }

        return success;
    }

protected:
    // 可被重写的实现
    virtual bool doConnect(const std::string &connectionString)
    {
        std::cout << "Base connection to " << connectionString << std::endl;
        return true; // 假设默认实现总是成功
    }

    virtual void logConnectionAttempt(const std::string &connectionString)
    {
        std::cout << "Attempting to connect to " << connectionString << std::endl;
    }
};

class MySQLConnection : public DBConnection
{
protected:
    virtual bool doConnect(const std::string &connectionString) override
    {
        std::cout << "MySQL specific connection to " << connectionString << std::endl;
        // MySQL特定的连接逻辑
        return true;
    }
};

class PostgreSQLConnection : public DBConnection
{
protected:
    virtual bool doConnect(const std::string &connectionString) override
    {
        std::cout << "PostgreSQL specific connection to " << connectionString << std::endl;
        // PostgreSQL特定的连接逻辑
        return true;
    }
};

// 相机
class BaseCamera
{
public:
    // 公共非虚接口
    bool connectCamera(const std::string &ipAddress, int port = 8080)
    {
        // 前置条件：验证IP地址格式
        if (!isValidIPAddress(ipAddress))
        {
            std::cerr << "Invalid IP address format: " << ipAddress << std::endl;
            return false;
        }

        std::cout << "Attempting to connect to camera at " << ipAddress << ":" << port << std::endl;

        // 记录连接尝试
        logConnectionAttempt(ipAddress, port);

        // 调用派生类实现的具体连接方法
        bool connected = doConnect(ipAddress, port);

        // 后置处理
        if (connected)
        {
            std::cout << "Camera connected successfully" << std::endl;
            m_isConnected = true;
            initializeAfterConnection();
        }
        else
        {
            std::cout << "Failed to connect to camera" << std::endl;
        }

        return connected;
    }

    bool isConnected() const { return m_isConnected; }

    // 其他公共方法...
    void disconnect()
    {
        if (m_isConnected)
        {
            doDisconnect();
            m_isConnected = false;
            std::cout << "Camera disconnected" << std::endl;
        }
    }

protected:
    // 派生类需要实现的保护虚函数
    virtual bool doConnect(const std::string &ipAddress, int port) = 0;
    virtual void doDisconnect() = 0;

    // 可选的钩子函数，派生类可以重写
    virtual void initializeAfterConnection()
    {
        std::cout << "Performing base camera initialization" << std::endl;
    }

    virtual void logConnectionAttempt(const std::string &ipAddress, int port)
    {
        std::cout << "Connection attempt logged" << std::endl;
    }

private:
    bool m_isConnected = false;

    bool isValidIPAddress(const std::string &ipAddress)
    {
        // 简单的IP地址验证逻辑
        // 实际应用中可能需要更复杂的验证
        std::regex ipPattern("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$");
        return std::regex_match(ipAddress, ipPattern);
    }
};

// 特定型号相机的实现
class HikVisionCamera : public BaseCamera
{
protected:
    virtual bool doConnect(const std::string &ipAddress, int port) override
    {
        std::cout << "HikVision camera specific connection to " << ipAddress << ":" << port << std::endl;
        // HikVision SDK连接代码
        return true; // 假设连接成功
    }

    virtual void doDisconnect() override
    {
        std::cout << "HikVision camera specific disconnection" << std::endl;
        // HikVision SDK断开连接代码
    }

    virtual void initializeAfterConnection() override
    {
        BaseCamera::initializeAfterConnection(); // 调用基类初始化
        std::cout << "Setting HikVision camera specific parameters" << std::endl;
        // 设置HikVision相机特定参数
    }
};

// 另一个品牌相机
class DahuaCamera : public BaseCamera
{
protected:
    virtual bool doConnect(const std::string &ipAddress, int port) override
    {
        std::cout << "Dahua camera specific connection to " << ipAddress << ":" << port << std::endl;
        // 大华SDK连接代码
        return true; // 假设连接成功
    }

    virtual void doDisconnect() override
    {
        std::cout << "Dahua camera specific disconnection" << std::endl;
        // 大华SDK断开连接代码
    }
};